/*
 * SimulationNode.cpp
 *
 *  Created on: 30/10/2011
 *      Author: godinho
 */

#include <iostream>
#include "SimulationNode.h"
#include "NodeInput.h"
#include "TLSPhase.h"
#include "TLSLink.h"

SimulationNode::SimulationNode(std::string id, int x, int y) : mId(id), mX(x), mY(y){
	mCurrentPhaseTimeout = 0;
	mCurrentPhase = 0;
	mCurrentPhaseIndex = -1;
}

SimulationNode::~SimulationNode() {
    mNodeInput.clear();
}

NodeInput* SimulationNode::getNodeInput(SimulationNode* node) {
	std::map<SimulationNode*, NodeInput*>::iterator it;

	it = mNodeInput.find(node);

	if(it == mNodeInput.end()) {
		return 0;
	}
	return (*it).second;
}

std::map<SimulationNode*, NodeInput*> SimulationNode::getNodeInputMap() {
	return mNodeInput;
}

std::string SimulationNode::getId() {
	return mId;
}

TLSPhase* SimulationNode::getCurrentPhase() {
	return mCurrentPhase;
}

void SimulationNode::addPhase(TLSPhase* phase) {
	std::vector<TLSLink*> links = phase->getLinks();
	std::vector<TLSLink*>::iterator it;

	for(it = links.begin(); it != links.end(); it++) {
		(*it)->setIntersectionNode(this);
	}

	if(mCurrentPhaseIndex == -1) {
		mCurrentPhase = phase;
		mCurrentPhaseIndex = 0;
	}

	phase->setId(mPhases.size());
	mPhases.push_back(phase);
}

std::vector<TLSPhase*> SimulationNode::getPhases() {
	return mPhases;
}

int SimulationNode::getX() {
	return mX;
}

int SimulationNode::getY() {
	return mY;
}

void SimulationNode::addIncomingNode(SimulationNode* incoming, int travelTime) {
    addIncomingNode(incoming, travelTime, 0, 1);
}

void SimulationNode::addIncomingNode(SimulationNode* incoming, int travelTime, int initialCarsOnTravel, int numLanes) {
    NodeInput* nodeInput = new NodeInput(travelTime);

    nodeInput->setNumLanes(numLanes);
    nodeInput->setCarsInTransfer(initialCarsOnTravel);

    mNodeInput[incoming] = nodeInput;
}

void SimulationNode::addOutcomingNode(SimulationNode* outcoming) {
	mOutcomingNode.push_back(outcoming);
}

std::vector<SimulationNode*> SimulationNode::getOutcomingNodes() {
	return mOutcomingNode;
}

bool SimulationNode::decrementCurrentPhaseTime() {
	mCurrentPhaseTimeout--;

	return mCurrentPhaseTimeout <= 0;
}

void SimulationNode::nextPhase() {
	if(mPhases.size() == 0) {
		return;
	}

	mCurrentPhaseIndex = (mCurrentPhaseIndex+1)%mPhases.size();
	mCurrentPhase = mPhases[mCurrentPhaseIndex];
	mCurrentPhaseTimeout = mCurrentPhase->getDuration();
}

void SimulationNode::collectCars() {
	std::map<SimulationNode*, NodeInput*>::iterator nodeInputIt;

	for(nodeInputIt = mNodeInput.begin(); nodeInputIt != mNodeInput.end(); nodeInputIt++){
		(*nodeInputIt).second->popAll();
	}
}

bool SimulationNode::isBorder() {
	return (mOutcomingNode.size() == 0) || (mNodeInput.size() == 0);
}

bool SimulationNode::isNetworkOutputNode() {
	return mOutcomingNode.size() == 0;
}

bool SimulationNode::isNetworkInputNode() {
	return mNodeInput.size() == 0;
}

bool SimulationNode::hasPhases() {
	return mPhases.size() > 0;
}

int SimulationNode::getOutcomingNodesCount() {
    return mOutcomingNode.size();
}

int SimulationNode::getIncomingNodesCount() {
    return mNodeInput.size();
}
